﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using TireService.Data;
using DevExpress.Web.ASPxCallback;
using System.Web.Security;
using DevExpress.Web.ASPxClasses;

namespace TireService.Web.UserControls
{
    public partial class ucCreateSubscriptionAndCar : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void callbackCreateSubscriptionAndCarPanel_Callback(object source, DevExpress.Web.ASPxClasses.CallbackEventArgsBase e)
        {
            LoadUserControl(Convert.ToInt32(e.Parameter));
        }

        /// <summary>
        /// Public function for loading usercontrol
        /// </summary>
        public void LoadUserControl(int CustomerId)
        {
            // Show usercontrol edit form
            pCreateSubscriptionAndCar.Visible = true;

            // Initiate datalayer
            TireServiceDB db = new TireServiceDB();

            // Load form data
            LoadUserControlData(db);

            if (CustomerId != 0)
            {
                // Preselect customer in list
                LoadCustomer(CustomerId, db);

                ddlSelectCustomer.Items.FindByValue(CustomerId.ToString()).Selected = true;
            }
            else
            {
                // Customer not selected
                // No action
            }
        }

        /// <summary>
        /// Function that load form data for form
        /// </summary>
        /// <param name="db">Connection to database</param>
        private void LoadUserControlData(TireServiceDB db)
        {
            ddlSelectCustomer.DataSource = db.GetCustomersView();
            ddlSelectCustomer.ValueField = "CustomerId";
            ddlSelectCustomer.DataBind();

            ddlCarBrand.DataSource = db.GetCarBrand();
            ddlCarBrand.TextField = "Description";
            ddlCarBrand.ValueField = "CarBrandId";
            ddlCarBrand.DataBind();

            ddlCarStatus.DataSource = db.GetCarStatus();
            ddlCarStatus.TextField = "Description";
            ddlCarStatus.ValueField = "CarStatusId";
            ddlCarStatus.DataBind();
        }

        /// <summary>
        /// Function that load customer
        /// </summary>
        /// <param name="CustomerId">Id on customer</param>
        /// <param name="db">Connection to database</param>
        private void LoadCustomer(int CustomerId, TireServiceDB db)
        {
            // Fetch Customer
            Customer customer = db.GetCustomer(CustomerId);

            // Set values in form
            if (customer != null)
            {
                // Show possible adresses to select from if tireset should be returned
                ddlNewCarPickUpCustomerTireSetSelectAddress.Items.Clear();
                string add1 = customer.Address + "|" + customer.ZipCode + "|" + customer.City;
                string add2 = customer.SecondaryAddress + "|" + customer.SecondaryZipCode + "|" + customer.SecondaryCity;
                string add3 = "-- Anden adresse --";
                
                ddlNewCarPickUpCustomerTireSetSelectAddress.Items.Add(add1, 0);
                ddlNewCarPickUpCustomerTireSetSelectAddress.Items.Add(add2, 1);
                ddlNewCarPickUpCustomerTireSetSelectAddress.Items.Add(add3, 2);
            }
        }

        /// <summary>
        /// Callback function on customerdropdownlist - selected pickup adress is updated based on selected customer
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e">Id on customer</param>
        protected void ddlNewCarPickUpCustomerTireSetSelectAddress_Callback(object source, CallbackEventArgsBase e)
        {
            // Instantiate datalayer
            TireServiceDB db = new TireServiceDB();

            LoadCustomer(Convert.ToInt32(e.Parameter), db);
        }

        /// <summary>
        /// Callback function that creates new subscription with car
        /// </summary>
        protected void callBackCreateSubscriptionAndCar_Callback(object sender, CallbackEventArgs e)
        {
            try
            {
                // Get values from client 
                // 0: CustomerId - int
                // 1: SubscriptionId - int
                // 2: LastRenewalDate - datetime
                // 3: Price - decimal
                // 4: BalancingIncluded (true/false) 
                // 5: InvoiceCustomer (true/false)
                // 6: CarRegistrationNumber - string
                // 7: CarBrand - string
                // 8: Model - string
                // 9: EngineSize - string
                // 10: FuelType - int
                // 11: Year - int
                // 12: Color - string 
                // 13: CarStatus - int 
                // 14: CurrentTireSet - int  
                // 15: LockingBoltsCurrentTireSet (true/false) 
                // 16: CarOtherTireSet - int
                // 17: LockingBoltsOtherTireSet (true/false)
                // 18: NewCarInvoiceCustomer (true/false) (optional)
                // 19: NewCarInvoicePrice (optional) - decimal
                // 20: Address (optional) - string
                // 21: ZipCode (optional) - string
                // 22: City (optional) - string
                // 23: Remark to address (optional) - string
                // 24: Note to employee (optional) - string
                // 25: Email Confirmation (true/false)

                string[] param = e.Parameter.Split('|');

                // Get UserId (for logging)
                Guid UserId = new Guid(Membership.GetUser().ProviderUserKey.ToString());

                // Initiate datalayer
                TireServiceDB db = new TireServiceDB();

                // Get customer
                Customer customer = db.GetCustomer(Convert.ToInt32(param[0]));

                // Get subscription 
                Subscription subscription = db.GetSubscription(Convert.ToInt32(param[1]));

                // Initiate customer subscription business logic
                CustomerSubscriptionBLL customersubscriptionBLL = new CustomerSubscriptionBLL();

                // Calculate subscription renew date
                // Renewal dates: 01/03 and 01/09
                DateTime LastRenewalDate = Convert.ToDateTime(param[2]);
                DateTime NextRenewalDate = customersubscriptionBLL.CalculateNextRenewalDate(LastRenewalDate, subscription);
                decimal Price = Convert.ToDecimal(param[3]);
                bool BalancingIncluded = Convert.ToBoolean(param[4]);

                // Create customersubscription
                CustomerSubscription customersubscription = new CustomerSubscription();
                customersubscriptionBLL.UpdateCustomerSubscription(db, customersubscription, customer, 0, subscription.SubscriptionId, LastRenewalDate, NextRenewalDate, false, BalancingIncluded, Price, UserId, true, "Oprettelse af abonnement og bil");

                // Create new car
                Car car = new Car();
                car.RegistrationNumber = Convert.ToString(param[6]);
                car.CarBrandId = Convert.ToInt32(param[7]);
                car.Model = Convert.ToString(param[8]);
                car.EngineSize = Convert.ToString(param[9]);
                car.FuelType = Convert.ToInt32(param[10]);
                car.Year = Convert.ToInt32(param[11]);
                car.Color = Convert.ToString(param[12]);
                car.CarStatusId = Convert.ToInt32(param[13]); // TODO: Consider if status is require service drive, create task automatic???

                // Add relationships to car
                customer.Cars.Add(car);
                customersubscription.Cars.Add(car);

                db.AddCar(car);

                // Instantiate task business logic layer
                TaskBLL taskBLL = new TaskBLL();

                // Declare invoice variable if invoicing is needed
                string invoiceid = string.Empty;

                // Declare string as input for message on tireset action
                string tiresetaction = "";

                // Get paying customer for invoicing and emailing confirmation
                CustomerBLL customerBLL = new CustomerBLL();
                int PayingCustomerId = customerBLL.GetPayingCustomerId(db, customer.CustomerId);
                Customer payingcustomer = db.GetCustomer(PayingCustomerId);

                // Initiate E-conomic interface
                EconomicInterface ecoInterface = new EconomicInterface();

                // Instantiate tiresetlog business logic
                TireSetLogBLL tiresetlogBLL = new TireSetLogBLL();

                // Placeholder for adding new tires to new car
                TireSet tireset1 = new TireSet();
                TireSet tireset2 = new TireSet();

                int OtherTireSetAction = Convert.ToInt32(param[16]); // 0: We will get tires on first service, 1: Pickup tires, 2: We have the tires
                
                // Add tiresets for new car
                TireSetBLL tiresetBLL = new TireSetBLL();
                ContainerCargoRoomBLL containerBLL = new ContainerCargoRoomBLL();

                // Determine what tires are on the car
                int tireset1status, tireset2status;
                int? tireset1container, tireset2container;
                bool tireset1lockingbolt, tireset2lockingbolt;

                int tiresetonstockstatus = (int)Shared.TireSetStatus.OnStock;

                if (OtherTireSetAction == 0)
                {
                    // Customer has tireset
                    tiresetonstockstatus = (int)Shared.TireSetStatus.PlacedAtCustomer;
                }
                if (OtherTireSetAction == 1)
                {
                    // Tireset should be picked up - create task
                    tiresetonstockstatus = (int)Shared.TireSetStatus.PlacedAtCustomer;
                    
                    // TODO: Create code for creating task
                }
                if (OtherTireSetAction == 2)
                {
                    // We already have the tireset
                    tiresetonstockstatus = (int)Shared.TireSetStatus.OnStock;

                    // TODO: Make code for selecting right container
                }

                // Check current tires on car
                if (Convert.ToString(param[14]) == "0")
                {
                    // Winter tires on car
                    tireset1status = tiresetonstockstatus;
                    tireset1container = containerBLL.ReturnNearestContainerCargoRoomId(db, float.Parse(customer.LatitudePrimary.ToString()), float.Parse(customer.LongitudePrimary.ToString()));
                    tireset1lockingbolt = Convert.ToBoolean(param[17]);
                    tireset2status = (int)Shared.TireSetStatus.MountedOnCar;
                    tireset2container = null;
                    tireset2lockingbolt = Convert.ToBoolean(param[15]);

                    if (OtherTireSetAction == 1)
                    {
                        // Create servicedrive task
                        Task task = taskBLL.CreateTask(db,
                                                    null,
                                                    (int)Shared.TaskType.ServiceDrive,
                                                    (int)Shared.TaskDetailType.ServiceDrive_PickUpTire,
                                                    (int)Shared.TaskTypeStatus.ServiceDrive_Created,
                                                    customer,
                                                    car,
                                                    tireset1,
                                                    param[20],
                                                    param[21],
                                                    param[22],
                                                    0,
                                                    param[23],
                                                    param[20],
                                                    param[21],
                                                    param[22],
                                                    0,
                                                    param[23],
                                                    param[24],
                                                    1,
                                                    UserId,
                                                    true);
                    }
                }
                else
                {
                    // Summer tires on car
                    tireset1status = (int)Shared.TireSetStatus.MountedOnCar;
                    tireset1container = null;
                    tireset1lockingbolt = Convert.ToBoolean(param[15]);
                    tireset2status = tiresetonstockstatus;
                    tireset2container = containerBLL.ReturnNearestContainerCargoRoomId(db, float.Parse(customer.LatitudePrimary.ToString()), float.Parse(customer.LongitudePrimary.ToString()));
                    tireset2lockingbolt = Convert.ToBoolean(param[17]);

                    if (OtherTireSetAction == 1)
                    {
                        // Create servicedrive task
                        Task task = taskBLL.CreateTask(db,
                                                    null,
                                                    (int)Shared.TaskType.ServiceDrive,
                                                    (int)Shared.TaskDetailType.ServiceDrive_PickUpTire,
                                                    (int)Shared.TaskTypeStatus.ServiceDrive_Created,
                                                    customer,
                                                    car,
                                                    tireset2,
                                                    param[20],
                                                    param[21],
                                                    param[22],
                                                    0,
                                                    param[23],
                                                    param[20],
                                                    param[21],
                                                    param[22],
                                                    0,
                                                    param[23],
                                                    param[24],
                                                    1,
                                                    UserId,
                                                    true);
                    }
                }

                tiresetBLL.UpdateTireSet(
                                    db,
                                    tireset1,
                                    car,
                                    (int)Shared.TireType.SummerTires,
                                    null,
                                    null,
                                    null,
                                    null,
                                    null,
                                    null,
                                    null,
                                    tireset1lockingbolt,
                                    false,
                                    false,
                                    false,
                                    false,
                                    null,
                                    null,
                                    tireset1status,
                                    null,
                                    tireset1container,
                                    true,
                                    false,
                                    null,
                                    UserId,
                                    null,
                                    true
                                );

                tiresetBLL.UpdateTireSet(
                                    db,
                                    tireset2,
                                    car,
                                    (int)Shared.TireType.WinterTires,
                                    null,
                                    null,
                                    null,
                                    null,
                                    null,
                                    null,
                                    null,
                                    tireset2lockingbolt,
                                    false,
                                    false,
                                    false,
                                    false,
                                    null,
                                    null,
                                    tireset2status,
                                    null,
                                    tireset2container,
                                    true,
                                    false,
                                    null,
                                    UserId,
                                    null,
                                    true
                                );

                // Commit changes to database
                db.SubmitChanges();

                // Check if invoicing needed
                if (Convert.ToBoolean(param[5]) | Convert.ToBoolean(param[18]))
                {
                    // Create invoice

                    // Create orderline for invoicing
                    List<EconomicInterface.EcoOrderLine> orderlines = new List<EconomicInterface.EcoOrderLine>();

                    if (Convert.ToBoolean(param[5]))
                    {
                        // Subscription

                        EconomicInterface.EcoOrderLine orderline = new EconomicInterface.EcoOrderLine();
                        orderline.ProductNumber = subscription.EconomicProductNumber; // Is not used - will be loaded from customersubscription
                        orderline.Description = "Abonnement"; // Is not used - will be loaded from customersubscription
                        orderline.Quantity = 1; // Is not used - will be loaded from customersubscription
                        orderline.UnitPrice = 1; // Is not used - will be loaded from customersubscription
                        orderline.CustomerSubscriptionId = customersubscription.CustomerSubscriptionId;

                        orderlines.Add(orderline);
                    }

                    if (Convert.ToBoolean(param[18]))
                    {
                        // Pickup of tireset
                        EconomicInterface.EcoOrderLine orderline = new EconomicInterface.EcoOrderLine();
                        orderline.ProductNumber = 3; // TODO: Make more dynamic
                        orderline.Description = "Afhentning af hjul for bil: " + car.RegistrationNumber;
                        orderline.Quantity = 1;
                        orderline.UnitPrice = Convert.ToDecimal(param[20]);

                        orderlines.Add(orderline);
                    }

                    // Create invoice in e-conomic
                    invoiceid = ecoInterface.CreateInvoice(db, customersubscription.CustomerId, car, orderlines, (!payingcustomer.ManualInvoicing));

                    // Extend text info for customer email with invoice
                    tiresetaction += "<br><br>I email er vedlagt faktura for udkørsler ifht. hjulsæt.";
                }

                // Check if email confirmation should be send to customer
                if (Convert.ToBoolean(param[25]))
                {
                    // Send email to customer (paying customer is always the one who receives email notification

                    // Initiate email service
                    EmailNotificationServices emailService = new EmailNotificationServices();
                    
                    // Check if invoicing has happend
                    if (Convert.ToBoolean(param[5]) | Convert.ToBoolean(param[18]))
                    {
                        emailService.CreateSubscriptionAndCar_SendCustomerNotification(payingcustomer.CustomerId, payingcustomer.Email, payingcustomer.Name, customersubscriptionBLL.GetSubscriptionNumber(customersubscription), car.RegistrationNumber, tiresetaction, invoiceid, ecoInterface.GetInvoice(Convert.ToInt32(invoiceid)), "Faktura" + invoiceid + ".pdf");
                    }
                    else
                    {
                        emailService.CreateSubscriptionAndCar_SendCustomerNotification(payingcustomer.CustomerId, payingcustomer.Email, payingcustomer.Name, customersubscriptionBLL.GetSubscriptionNumber(customersubscription), car.RegistrationNumber, tiresetaction);
                    }

                }

                // Dispose database connection
                db.Dispose();
            }
            catch (Exception ex)
            {
                // Error
                throw new ArgumentException("Fejl opstod: " + ex.Message);
            }
        }
    }
}